/*
 * Copyright 2021-2022 Open Kunlun Technology <https://www.openkunlun.io>
 */

package io.openkunlun.scalarpc.codegen.model

import scala.meta._

/**
 * @author kostas.kougios
 *         Date: 09/10/17
 */
case class TemplateEx private (meta: TemplateEx.Meta) extends CodeEx with ValEx.Contains with MetaEx.Contains {

  override def tree: Template = Template(meta.earlyStats.toList, meta.inits.toList, meta.self, meta.stats.toList)
  override def vals = meta.stats.collect(ValEx.parser)
  def extending: Seq[TypeEx] = meta.inits.map(_.tpe).map(TypeEx.apply)
  def withExtending(types: Seq[TypeEx]) = copy(
    meta = meta.copy(
      inits = types.map(_.meta.tpe).map(tpe => Init(tpe, Name("invalid"), Nil)).toList
    )
  )
}

object TemplateEx extends PartialParser[TemplateEx] {
  case class Meta(earlyStats: Seq[Stat], inits: Seq[Init], self: Self, stats: Seq[Stat]) extends MetaEx

  override def parser: PartialFunction[Tree, TemplateEx] = {
    case template"{ ..$earlyStats } with ..$inits { $self => ..$stats }" =>
      TemplateEx(Meta(earlyStats, inits, self, stats))
  }

  trait Contains[S] {
    def meta: MetaEx with MetaEx.Template

    def template: TemplateEx = TemplateEx.parser(meta.template)
    def withTemplate(t: TemplateEx): S = withTemplate(t.tree)
    protected def withTemplate(t: Template): S

    def extending: Seq[TypeEx] = template.extending
    def extendsTypes: Seq[TypeEx] = template.meta.inits.map(_.tpe).map(TypeEx.apply)
  }

}